package wint.help.mvc.security.csrf;

import javax.servlet.http.HttpSession;

import wint.help.mvc.WebConstants;
import wint.lang.magic.MagicList;
import wint.lang.utils.CollectionUtil;
import wint.lang.utils.RandomStringUtil;
import wint.lang.utils.StringUtil;
import wint.mvc.flow.FlowData;

/**
 * 
 * 
 * @author pister 2012-3-11 下午02:22:41
 */
public class CsrfTokenUtil {
	
	private static final int TOKEN_BUFFER_COUNT = 3;
	
	private static final int TOKEN_PART1_LENGTH = 4;
	
	private static final int TOKEN_PART2_LENGTH = 6;
	
	public static String getCurrentToken(FlowData flowData, String groupName, String tokenName) {
		MagicList<String> tokens = getTokensFromSession(flowData, groupName, tokenName);
		return tokens.get(0);
	}
	
	public static String nextToken(FlowData flowData, String groupName, String tokenName) {
		MagicList<String> tokens = getTokensFromSession(flowData, groupName, tokenName);
		HttpSession session = flowData.getSession();
		tokenName = makeTokenName(groupName, tokenName);
		if (tokens.size() == 1) {
			tokens = createTokens();
			session.setAttribute(tokenName, tokens.join(","));
			return tokens.get(0);
		} else {
			tokens.remove(0);
			session.setAttribute(tokenName, tokens.join(","));
			return tokens.get(0);
		}
	}
	
	private static MagicList<String> getTokensFromSession(FlowData flowData, String groupName, String tokenName) {
		tokenName = makeTokenName(groupName, tokenName);
		HttpSession session = flowData.getSession();
		String tokensString = (String)session.getAttribute(tokenName);
		MagicList<String> tokens = toTokens(tokensString);
		if (CollectionUtil.isEmpty(tokens)) {
			tokens = createTokens();
		}
		session.setAttribute(tokenName, tokens.join(","));
		return tokens;
	}
	
	private static String makeTokenName(String groupName, String tokenName) {
		return WebConstants.CSRF_TOKEN_KEY_PREFIX + groupName + "_" + tokenName;
	}
	
	private static MagicList<String> toTokens(String tokensString) {
		if (StringUtil.isEmpty(tokensString)) {
			return null;
		}
		String[] tokens = tokensString.split(",");
		if (tokens == null || tokens.length == 0) {
			return null;
		}
		return MagicList.wrap(tokens);
	}
	
	private static MagicList<String> createTokens() {
		MagicList<String> tokens = MagicList.newList(TOKEN_BUFFER_COUNT);
		String part1 = RandomStringUtil.randomAlphanumeric(TOKEN_PART1_LENGTH);
		for (int i = 0; i < TOKEN_BUFFER_COUNT; ++i) {
			String part2 = RandomStringUtil.randomAlphanumeric(TOKEN_PART2_LENGTH);
			String token = part1 + "_" + part2;
			tokens.add(token);
		}
		return tokens;
	}
	

}
